package org.smartboot.flow.testcase.extension;

import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smartboot.flow.core.EngineContext;
import org.smartboot.flow.core.ExecutionListener;
import org.smartboot.flow.core.Extensible;
import org.smartboot.flow.core.Key;
import org.smartboot.flow.core.parser.ExtensionAttrParser;

/**
 * @author qinluo
 * @date 2023-04-14 15:16:29
 * @since 1.0.0
 */
public class EscapeWarningExtensionAttrParser implements ExtensionAttrParser {

    private static final Logger LOGGER = LoggerFactory.getLogger(EscapeWarningExtensionAttrParser.class);

    @Override
    public String prefix() {
        // 可扩展属性的前缀
        return "escapeWarning";
    }

    @Override
    public ExecutionListener getListener() {
        return WarningListener.INSTANCE;
    }

    public static class WarningListener implements ExecutionListener {

        private static final ExecutionListener INSTANCE = new WarningListener();

        @Override
        public <T, S> void beforeExecute(EngineContext<T, S> context, Object object) {
            if (!(object instanceof Extensible)) {
                return;
            }

            Extensible extensible = (Extensible) object;
            String value = extensible.getValue("escapeWarning", "timeout");
            if (!NumberUtils.isNumber(value)) {
                return;
            }

            context.putExt(Key.of("startMills", object), System.currentTimeMillis());
        }

        @Override
        public <T, S> void afterExecute(EngineContext<T, S> context, Object object, Throwable ex) {
            if (!(object instanceof Extensible)) {
                return;
            }

            Extensible extensible = (Extensible) object;
            String value = extensible.getValue("escapeWarning", "timeout");
            if (!NumberUtils.isNumber(value)) {
                return;
            }
            long limit = NumberUtils.toLong(value);
            long escaped = System.currentTimeMillis() - context.getExt(Key.<Long>of("startMills", object));
            if (escaped > limit) {
                LOGGER.warn("component execute {}ms, escaped {}ms, request = {}", limit, escaped, context.getReq());
            }
        }
    }
}
